package personal.jason.hmm.models_handle;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Handle the dict related operation
 * 
 * documents：
 * |
 * |-state_dic.txt            "number/word" size:n
 * |-obervate_dic.txt         "number/word" size:m
 *         
 * @author Jason_wbw
 *
 */

public class DictHandler {
	
	String modelPath = "./models/";
	
	Map<Integer, String> states = null;
	Map<Integer, String> observes = null;
	
	public DictHandler(String modelPath){
		this.modelPath = modelPath;
	}
	
	/**
	 * build the state and observation dict and change the train file
	 * 
	 * the format is "number/word"
	 * 
	 * @param inputFile
	 * @param changedInputFile
	 * @throws IOException 
	 */
	public void buildDictAndChange(String inputFile, String changedInputFile) throws IOException{
		String stateOutput = this.modelPath+"state_dic.txt";
		String observationOutput = this.modelPath+"obervate_dic.txt";
		
		Map<String, Integer> states = new HashMap<String, Integer>();
		Map<String, Integer> observes = new HashMap<String, Integer>();
		
		//get all state and observation
		BufferedReader reader = new BufferedReader(new FileReader(inputFile));
		String tempString = null;
		while ((tempString = reader.readLine()) != null) {
			String[] tems = tempString.split(" ");
			for(String tem:tems){
				String[] elem = tem.split("/");
				states.put(elem[1].trim(), states.size());
				observes.put(elem[0].trim(), observes.size());
			}
		}
		reader.close();
		
		FileWriter writer;
		
		//write state to file
		writer = new FileWriter(stateOutput, true);
		for(Map.Entry<String,Integer> entry:states.entrySet()){
			writer.write(entry.getValue()+"/"+entry.getKey()+" ");
		}
		writer.close();
		
		//write observation to file
		writer = new FileWriter(observationOutput, true);
		for(Map.Entry<String,Integer> entry:observes.entrySet()){
			writer.write(entry.getValue()+"/"+entry.getKey()+" ");
		}
		writer.close();
		
		//change the input file
		writer = new FileWriter(changedInputFile, true);
		
		reader = new BufferedReader(new FileReader(inputFile));
		while ((tempString = reader.readLine()) != null) {
			String[] tems = tempString.split(" ");
			for(String tem:tems){
				String[] elem = tem.split("/");
				writer.write(observes.get(elem[0])+"/"+states.get(elem[1])+" ");
			}
			writer.write("\n");
		}
		reader.close();
	}
	
	/**
	 * load the dict to memory
	 * @throws IOException 
	 * @throws NumberFormatException 
	 */
	public void loadDict() throws NumberFormatException, IOException{
		states = new HashMap<Integer, String>();
		observes = new HashMap<Integer, String>();
		
		String stateOutput = this.modelPath+"state_dic.txt";
		String observationOutput = this.modelPath+"obervate_dic.txt";
		
		//get all state 
		BufferedReader reader = new BufferedReader(new FileReader(stateOutput));
		String tempString = null;
		while ((tempString = reader.readLine()) != null) {
			String[] tems = tempString.split(" ");
			for(String tem:tems){
				String[] elem = tem.split("/");
				states.put(Integer.parseInt(elem[0].trim()), 
						elem[1].trim());
			}
		}
		reader.close();
		
		//get all observation
		reader = new BufferedReader(new FileReader(observationOutput));
		while ((tempString = reader.readLine()) != null) {
			String[] tems = tempString.split(" ");
			for(String tem:tems){
				String[] elem = tem.split("/");
				observes.put(Integer.parseInt(elem[0].trim()), 
						elem[1].trim());
			}
		}
		reader.close();
	}
	
	/**
	 * get state content by number
	 * @param number
	 * @return content; null if haven't load models
	 */
	public String getState(int number){
		if(this.states!=null)
			return this.states.get(number);
		return null;
	}
	
	/**
	 * get observe content by number
	 * @param number
	 * @return content; null if haven't load models
	 */
	public String getObserve(int number){
		if(this.observes!=null)
			return this.observes.get(number);
		return null;
	}
}
